// 探测器
use crate::core::{Command, DeviceInfo};
use log::error;
use std::{
    collections::HashMap,
    net::{IpAddr, Ipv4Addr, SocketAddr},
    sync::Arc,
    time::{Duration, Instant},
};
use tokio::net::UdpSocket;
use tokio::{
    sync::{Mutex, mpsc},
    time,
};
use uuid::Uuid;
// 启动设备发现服务
pub async fn start_discovery_service(
    device_name: String,
    devices: Arc<Mutex<HashMap<u64, DeviceInfo>>>,
    cmd_tx: mpsc::Sender<Command>,
) -> Result<DiscoveryService, Box<dyn std::error::Error + Send + Sync>> {
    let address = crate::CONFIG.get().unwrap().address.clone();
    let multicast_ip: Ipv4Addr = address.multicast_ip.parse()?;
    let multicast_addr = SocketAddr::new(IpAddr::V4(multicast_ip), 8888);
    let udp_socket = UdpSocket::bind(format!("{}:{}", address.this_network_ip, "0")).await?;
    udp_socket.join_multicast_v4(multicast_ip, Ipv4Addr::UNSPECIFIED)?;

    let udp_socket = Arc::new(udp_socket);

    let transfer_port = address.transfer_port; // 文件传输服务端口

    let local_device = DeviceInfo {
        id: Uuid::new_v4().to_string(),
        name: device_name,
        ip: get_local_ip().unwrap_or(IpAddr::V4(Ipv4Addr::LOCALHOST)),
        transfer_port,
        last_seen: Instant::now(),
    };
    let local_device_id = local_device.id.clone();
    let broadcast_device = local_device.clone();
    // 广播自身信息的任务
    let broadcast_handle = tokio::spawn({
        let socket = Arc::clone(&udp_socket);
        let device = broadcast_device; // 使用克隆的副本
        async move {
            let mut interval = time::interval(Duration::from_secs(2));
            loop {
                let data = serde_json::to_vec(&device).unwrap();
                if let Err(e) = socket.send_to(&data, multicast_addr).await {
                    error!("广播错误: {}", e);
                }
                interval.tick().await;
            }
        }
    });
    // 监听设备信息的任务
    let listen_handle = tokio::spawn({
        let socket = Arc::clone(&udp_socket);
        let devices = devices.clone();
        async move {
            let mut buf = [0; 1024];
            loop {
                match socket.recv_from(&mut buf).await {
                    Ok((len, src_addr)) => {
                        if let Ok(mut device) = serde_json::from_slice::<DeviceInfo>(&buf[..len]) {
                            // 使用克隆的ID进行比较
                            if device.id != local_device_id {
                                device.last_seen = Instant::now();
                                let mut devices = devices.lock().await;
                                devices.insert(
                                    device.id.parse::<u64>().unwrap(),
                                    DeviceInfo {
                                        ip: src_addr.ip(),
                                        ..device
                                    },
                                );
                            }
                        }
                    }
                    Err(e) => error!("接收错误: {}", e),
                }
            }
        }
    });

    // 设备清理任务
    let cleanup_handle = tokio::spawn({
        let devices = devices.clone();
        async move {
            let mut interval = time::interval(Duration::from_secs(10));
            loop {
                {
                    let mut devices = devices.lock().await;
                    devices.retain(|_, info| info.last_seen.elapsed() < Duration::from_secs(30));
                }
                interval.tick().await;
            }
        }
    });

    Ok(DiscoveryService {
        handle: tokio::spawn(async move {
            tokio::try_join!(broadcast_handle, listen_handle, cleanup_handle)?;
            Ok(())
        }),
        local_device,
        local_transfer_port: transfer_port,
    })
}

pub struct DiscoveryService {
    pub handle: tokio::task::JoinHandle<Result<(), Box<dyn std::error::Error + Send + Sync>>>,
    pub local_device: DeviceInfo,
    pub local_transfer_port: u16,
}

// 获取本地IP地址
fn get_local_ip() -> Option<IpAddr> {
    local_ip_address::local_ip().ok()
}
